package com.bjsxt.service.impl;

import com.bjsxt.constant.LoginConstant;
import org.apache.catalina.authenticator.jaspic.SimpleAuthConfigProvider;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class UserServiceDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        ServletRequestAttributes requestAttributes =     (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            String loginType =    requestAttributes.getRequest().getParameter("login_type"); //区分后台人员还是用户

        if(StringUtils.isEmpty(loginType)){
                throw new AuthenticationServiceException("登录类型不能为NULL");
        }
        UserDetails userDetails = null;
        try {
           String grant_type =   requestAttributes.getRequest().getParameter("grant_type");//refresh_token 纠正
                if(LoginConstant.REFRESH_TYPE.equals(grant_type.toUpperCase())){
                    username = adjustUsername(username,loginType);
                }
        switch (loginType)
                
        {
            case LoginConstant.ADMIN_TYPE:

                userDetails =  loadSysUserByUsername(username);
                break;
            case LoginConstant.MEMBER_TYPE:
                userDetails =  loadMemberUserbyUsername(username);
                break;
            default:
                throw new AuthenticationServiceException("不支持登陆方式 "+ loginType);
        } }catch (IncorrectResultSizeDataAccessException e){
            throw new UsernameNotFoundException("用户名"+username+"不存在");
        }

        return userDetails;
    }

    /**
     * 纠正用户的名称
     * @param username 用户id
     * @param loginType admin_type  member_type
     * @return
     */
    private String adjustUsername(String username, String loginType) {
        if(LoginConstant.ADMIN_TYPE.equals(loginType))
        {
            return jdbcTemplate.queryForObject(LoginConstant.QUERY_ADMIN_USER_WITH_ID,String.class,username);
        }
        if (LoginConstant.MEMBER_TYPE.equals(loginType))
        {
            return jdbcTemplate.queryForObject(LoginConstant.QUERY_MEMBER_USER_WITH_ID,String.class,username) ;
        }
            return username;

    }

    private UserDetails loadSysUserByUsername(String username)
    {
        //1使用用户名查询用户
       return jdbcTemplate.queryForObject(LoginConstant.QUERY_ADMIN_SQL, new RowMapper<User>() {
            @Override
            public User mapRow(ResultSet rs, int i) throws SQLException {
                if(rs.wasNull()){
                    throw new UsernameNotFoundException("用户名"+username+"不存在");
                }
                long id = rs.getLong("id");
                String password = rs.getString("password");
                int status = rs.getInt("status");
                return new User(String.valueOf(id)//id->username
                                ,password,
                                status ==1,
                        true,
                        true,
                        true,
                        getSysUserPermissions(id)) ;
            }
        },username);
        //2 查询用户对应权限
        //3 封装成userdetails对象
    }

    /**
     * 通过用户id 查询用户的权限
     * @param id
     * @return
     */
    private Collection<? extends GrantedAuthority> getSysUserPermissions(long id) {
        //1 当用户为超级管理员时 ， 拥有所以的权限数据
       String Role_code =  jdbcTemplate.queryForObject(LoginConstant.QUERY_ROLE_CODE_SQL,String.class,id);
        List<String>permission = null;
       if(LoginConstant.ADMIN_ROLE_CODE.equals(Role_code))
       {
           permission =    jdbcTemplate.queryForList(LoginConstant.QUERY_ALL_PERMISSIONS,String.class);

       }else
       {
           permission =  jdbcTemplate.queryForList(LoginConstant.QUERY_PERMISSION_SQL,String.class,id);
       }
        //2 普通用户，需要角色 -》 权限数据

        if(permission == null|| permission.isEmpty())
        {
            return Collections.emptySet();
        }
        return permission.stream()
                .distinct()//去重
                .map(perm->new SimpleGrantedAuthority(perm))
                .collect(Collectors.toSet());

    }


    /**
     * 普通用户登录
     * @param username
     * @return
     */
    private UserDetails loadMemberUserbyUsername(String username)
    {

        return jdbcTemplate.queryForObject(LoginConstant.QUERY_MEMBER_SQL, new RowMapper<UserDetails>() {
            @Override
            public User mapRow(ResultSet rs, int i) throws SQLException {
                if(rs.wasNull())
                {
                    throw  new UsernameNotFoundException(username+"不存在");
                }
                Long id = rs.getLong("id");
                String password =  rs.getString("password");
                int status =  rs.getInt("status");

                return new User(String.valueOf(id),
                               password,
                                status ==1,
                        true,
                        true,
                        true,
                        Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"))) ;
            }
        },username,username);
    }


















}
